# coding:utf-8
# 道具管理

import traceback, uuid
from sqlalchemy import and_, or_
import glog, gdb
from item import *
from db_tables import *


def _pack(d): return repr(d)
def _unpack(d): return eval(d)


# { role_id : {item_id1 : item1, ..}, .. }
data = {}

def init ():
    pass


# 取得道具
def get (owner, item_id):
    items = _get_owner_data(owner)
    if item_id not in items:
        glog.error("item_mgr>get, no this id, owner:%s, id:%s" % (owner,item_id))
        return None
    return cars[item_id]


# 获得全部道具
def get_items_by_owner (owner):
    items = _get_owner_data(owner)
    return items.values()


# 增加道具数量
def add (owner, item_type, amount):
    role_data = _get_owner_data(owner)
    items = _get_items_by_type(role_data, item_type)
    cell_max = _get_max_amount_per_cell(item_type)

    left = amount # 待增加
    for item in items:
        if item.amount < cell_max: # 补足
            toadd = min(cell_max - item.amount, left)
            item.amount += toadd
            left -= toadd
        else:
            pass
        if left <= 0: break

    while left > 0:
        # create item
        item_amount = min(cell_max , left)
        left -= item_amount
        item = _create_item(owner, item_type, item_amount)
        role_data[item.id] = item

    #print '_get_items_by_type:', _get_items_by_type(role_data, item_type)
    glog.debug('item_mgr>add OK, type:%s amount:%d' %(str(item_type), amount))
    return save_owner_data(owner)


# 减少道具数量
def remove (owner, item_type, amount):
    role_data = _get_owner_data(owner)
    items = _get_items_by_type(role_data, item_type)
    item_amount = sum( [ x.amount for x in items ] )

    if item_amount < amount:
        glog.error('item_mgr>remove FAILED, not enough (has:%d need:%d), type:%s' % (item_amount, amount, str(item_type)))
        return False

    left = amount # 待减少
    for item in items:
        if item.amount > left: # enough
            item.amount -= left
            left = 0
            break
        else: # not enough
            left -= item.amount
            role_data.pop(item.id) # del item 
    
    #print '_get_items_by_type:', _get_items_by_type(role_data, item_type)
    glog.debug('item_mgr>remove OK, type:%s amount:%d' %(str(item_type), amount))
    return save_owner_data(owner)


# 取得道具总数
def get_item_amount_by_type(owner, item_type):
    role_data = _get_owner_data(owner)
    items = _get_items_by_type(role_data, item_type)
    amount = sum( [ x.amount for x in items ] )
    return amount


def _get_item_by_id (owner_data, id):
    return owner_data.get(id, None)


def _get_items_by_type (owner_data, type):
    res = []
    for id, item in owner_data.iteritems():
        if type == item.type:
            res.append(item)
    return res


# 取得单格道具的上限
def _get_max_amount_per_cell (type):
    return 100  #* test


def _create_item (owner, type, amount):
    item = Item()
    item.id = uuid.uuid1().hex
    item.owner = owner
    item.type = type
    item.amount = amount

    return item


# --------------------------------------------------------
def _get_owner_data (owner): 
    if owner not in data:
        items = _load_db(owner)
        data[owner] = items
    return data[owner]


def save_owner_data (owner):
    res = _save_db(owner, _get_owner_data(owner))
    if not res:
        glog.error('item_mgr>save_owner_data FAILED, owner:%s' % owner) 
    return res
    

# 从数据库中加载数据
def _load_db (owner):
    role_data = _unpack( db_get_data(owner) )
    
    items = {}
    for id, adata in role_data.iteritems():
        item = Item()
        item.id = id
        item.from_dictionary(adata)
        items[item.id] = item

    #glog.log("car_mgr>_load_db, owner:%s" % owner)
    return items


def _save_db (owner, data):
    role_data = {}
    for id, adata in data.iteritems():
        role_data[id] = adata.to_dictionary()

    return db_set_data( owner, _pack(role_data) )


# ------------------------------------------------------
def db_get_data (owner):
    ses = gdb.get_session()
    res = ses.query(DBItem).filter_by(id=owner).all() # only one
    if len(res) > 0:
        return res[0].data
    else:
        return "{}"

def db_set_data (owner, data):
    ses = gdb.get_session()
        
    res = ses.query(DBItem).filter_by(id=owner).all()
    if len(res) > 0:
        # update
        try:
            record = res[0]
            record.data = data
            ses.commit()
            return True
        except Exception, e:
            print traceback.format_exc()
            ses.rollback()
            return False
    else:
        # insert
        try:
            ses.add(DBItem(owner, data))
            ses.commit()
            return True
        except Exception, e:
            print traceback.format_exc()
            ses.rollback()
            return False

# -------------------------------------------------
def test():
    print "item_mgr test ----------"
    import role_mgr
    role = role_mgr.get_one_role_by_account('test')

    print "test add"
    add(role.id, 1001, 1111)

    print "test remove 1"
    remove(role.id, 1001, 1)

    print "test remove 2"
    remove(role.id, 1001, 1000)

    print "test remove 3"
    remove(role.id, 1001, 1000)

    print "item_mgr test end ----------"